/// Copyright (c) Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace TfsTasks
{
    public class Checkin : Task
    {
        #region Private Fields
        private string _author = "";
        private string _comment = "";
        private string _notes = "";
        private string _override = "";
        private bool _recursive;
        private bool _saved;
        private string _itemSpec = "";
        private string _shelvesetName = "";
        private string _shelvesetOwner = "";
        private string _teamFoundationServerUrl = "";
        #endregion

        #region Public Properties
        // The [Required] attribute indicates a required property.
        // If a project file invokes this task without passing a value
        // to this property, the build will fail immediately.
        [Required]
        public string TeamFoundationServerUrl
        {
            get
            {
                return _teamFoundationServerUrl;
            }
            set
            {
                _teamFoundationServerUrl = value;
            }
        }

        public string Author
        {
            get
            {
                return _author;
            }
            set
            {
                _author = value;
            }
        }

        public string Comment
        {
            get
            {
                return _comment;
            }
            set
            {
                _comment = value;
            }
        }

        public string Notes
        {
            get
            {
                return _notes;
            }
            set
            {
                _notes = value;
            }
        }

        public string Override
        {
            get
            {
                return _override;
            }
            set
            {
                _override = value;
            }
        }

        public bool Recursive
        {
            get
            {
                return _recursive;
            }
            set
            {
                _recursive = value;
            }
        }

        public bool Saved
        {
            get
            {
                return _saved;
            }
            set
            {
                _saved = value;
            }
        }

        public string ItemSpec
        {
            get
            {
                return _itemSpec;
            }
            set
            {
                _itemSpec = value;
            }
        }

        public string ShelvesetName
        {
            get
            {
                return _shelvesetName;
            }
            set
            {
                _shelvesetName = value;
            }
        }

        public string ShelvesetOwner
        {
            get
            {
                return _shelvesetOwner;
            }
            set
            {
                _shelvesetOwner = value;
            }
        }

        #endregion

        #region Public Methods
        /// <summary>
        /// Execute the task. Checkin the pending changes.
        /// </summary>
        /// <returns>true</returns>
        /// <remarks>
        /// </remarks>
        public override bool Execute()
        {
            return this.ExecuteInternal();
        }
        #endregion

        #region Private Methods
        private bool ExecuteInternal()
        {
            Log.LogMessage(MessageImportance.High, "Checkin Task: Enter.");
            try
            {
                if (_teamFoundationServerUrl.Length == 0)
                {
                        Log.LogError("Team Foundation Server URL is empty.");
                        return false;                    
                }

                if (_shelvesetName.Length > 0 && _shelvesetOwner.Length == 0)
                {
                        Log.LogError("Shelveset owner is empty.");
                        return false;
                }
                
                if (_shelvesetName.Length == 0 && _shelvesetOwner.Length > 0)
                {
                        Log.LogError("Shelveset not specified.");
                        return false;
                }

                using (TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(_teamFoundationServerUrl))
                {
                    VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
                    if (versionControl == null)
                    {
                        Log.LogError("Failed to get VersionControlServer instance.");
                        return false;
                    }

                    // Get the pending changes in the current workspace...
                    Workspace workspace = null;
                    WorkspaceInfo[] workspaceInfoList = Workstation.Current.GetAllLocalWorkspaceInfo();

                    if (workspaceInfoList.Length == 0)
                    {
                        Log.LogError("No workspaces found. Please verify you have a workspace created and try again.");
                        return false;
                    }

                    if (workspaceInfoList.Length == 1)
                        workspace = versionControl.GetWorkspace(workspaceInfoList[0]);
                    else
                    {
                        List<WorkspaceInfo> workspaceInfoMatchingList = new List<WorkspaceInfo>();
                        for (int i = 0; i < workspaceInfoList.Length; i++)
                        {
                            Log.LogMessage(MessageImportance.High, "Workspace[{0}]: Name={1} - Owner={2}.", i, workspaceInfoList[i].Name, workspaceInfoList[i].OwnerName);

                            if (string.Compare(workspaceInfoList[i].ServerUri.ToString(), tfs.Uri.ToString(), true) == 0
                                && string.Compare(workspaceInfoList[i].OwnerName, tfs.AuthenticatedUserName, true) == 0
                                && string.Compare(workspaceInfoList[i].Computer, Workstation.Current.Name, true) == 0)
                            {
                                Log.LogMessage(MessageImportance.High, "Workspace[{0}] matched.", i);
                                workspaceInfoMatchingList.Add(workspaceInfoList[i]); // copy only matches.
                            }
                        }

                        if (workspaceInfoMatchingList.Count == 0)
                        {
                            Log.LogError("No workspace found matching server information. " +
                                "Please verify you have a workspace created and try again.");
                            return false;
                        }
                        else if (workspaceInfoMatchingList.Count == 1)
                        {
                            workspace = versionControl.GetWorkspace(workspaceInfoMatchingList[0]);
                        }
                        else // more than 1 --> cannot pick the right one.
                        {
                            Log.LogError("More than one workspace found matching server information. Please pick a workspace.");
                            return false;
                        }
                    }

                    PendingChange[] pendigChanges = workspace.GetPendingChanges(_itemSpec, _recursive? RecursionType.Full: RecursionType.None);
                    if (pendigChanges.Length == 0)
                    {
                        Log.LogError("No pending changes found.");
                        return false;
                    }
                    else
                    {
                        Log.LogMessage(MessageImportance.High, string.Format("Found {0} pending changes.", pendigChanges.Length));
                    }

                    // Prepare some data...
                    //if (_saved == true) ==> get the information from the workspace.
                    versionControl.QueryShelvesets(_shelvesetName, )
                    CheckinNoteFieldValue[] fieldValues = new CheckinNoteFieldValue[]{};
                    CheckinNote checkinNote = new CheckinNote(null);
                    WorkItemCheckinInfo[] workItemChanges = null;
                    PolicyOverrideInfo policyOverride = new PolicyOverrideInfo(_override, null);

                    // Checkin...
                    int changesetId = workspace.CheckIn(pendigChanges, _author, _comment, checkinNote, workItemChanges, policyOverride);

                    Log.LogMessage(MessageImportance.High, "Checkin was successful. Changeset Id: {0}.", changesetId);
                    return true;
                }
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex, true);
                return false;
            }
            finally
            {
                Log.LogMessage(MessageImportance.High, "Checkin Task: Exit.");
            }
        }
        #endregion
    }
}
